package org.lex.swing.widgets;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;

import org.lex.swing.Swings;


public class NetworkInterfaceTable extends JTable {
	private NetworkInterfaceTableModel tableModel = null;

	public static void main(String[] args) {
		Swings.setUseBoldMetalFont(false);
		Swings.show(new NetworkInterfaceTable(), false);
	}

	public NetworkInterfaceTable() {
		super();
		initialize();
	}

	public void setNetworkInterface(NetworkInterface i) {
		this.getTableModel().setNetworkInterface(i);
	}

	private void initialize() {
		// this.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
		this.setModel(this.getTableModel());
		this.setAutoCreateRowSorter(true);
		this.setFillsViewportHeight(true);
		int[] widths = { 200, 265 };
		TableColumnModel model = this.getColumnModel();
		for (int i = 0; i < model.getColumnCount(); i++)
			model.getColumn(i).setPreferredWidth(widths[i]);
	}

	private NetworkInterfaceTableModel getTableModel() {
		if (null == this.tableModel) {
			this.tableModel = new NetworkInterfaceTableModel();
		}
		return this.tableModel;
	}

	static class NetworkInterfaceTableModel extends AbstractTableModel {
		private static final String[] columnNames = { "Property", "Value" };
		private static final String[] propertyNames = { "Name", "Displayed Name", "Parent", "Sub Interface", "Inet Address",
				"Hardware Address (MAC)", "Maximum Transmission Unit (MTU)", "Is Loopback", "Is Point To Point", "Is Up", "Is Virtual",
				"Supports Multicast" };
		private String none = "(none)";
		private String yes = "Yes";
		private String no = "No";
		private NetworkInterface ni = null;

		public void setNetworkInterface(NetworkInterface i) {
			this.ni = i;
			this.fireTableDataChanged();
		}

		public String getColumnName(int column) {
			return columnNames[column];
		}

		public int getColumnCount() {
			return columnNames.length;
		}

		public int getRowCount() {
			return propertyNames.length;
		}

		public Object getValueAt(int row, int column) {
			if (0 == column)
				return propertyNames[row];
			if (null == ni)
				return "";
			switch (row) {
			case 0:
				// name
				return ni.getName();
			case 1:
				// displayed name
				return ni.getDisplayName();
			case 2:
				// parent
				NetworkInterface parent = ni.getParent();
				if (null == parent)
					return none;
				else
					return parent.getDisplayName();
			case 3:
				// sub interfaces
				return this.getSubInterfaces();
			case 4:
				// Inet Addresses
				return this.getInetAddressed();
			case 5:
				// mac
				return this.getMAC();
			case 6:
				// MTU
				return this.getMTU();
			case 7:
				// is Loopback
				return this.isLoopback();
			case 8:
				// is Point to Point
				return this.isPointToPoint();
			case 9:
				// is Up
				return this.isUp();
			case 10:
				// is virtual
				return this.wrapBoolean(ni.isVirtual());
			case 11:
				// supports Multicast
				return this.supportsMulticast();
			}
			return none;
		}

		private String getSubInterfaces() {
			Enumeration<NetworkInterface> ne = ni.getSubInterfaces();
			if (false == ne.hasMoreElements())
				return none;
			StringBuilder buffer = new StringBuilder();
			while (ne.hasMoreElements())
				buffer.append(ne.nextElement().getDisplayName()).append(", ");
			if (buffer.length() > 2)
				buffer.setLength(buffer.length() - 2);
			return buffer.toString();
		}

		private String getInetAddressed() {
			Enumeration<InetAddress> ei = ni.getInetAddresses();
			if (false == ei.hasMoreElements())
				return none;
			StringBuilder buffer = new StringBuilder();
			while (ei.hasMoreElements()) {
				InetAddress addr = ei.nextElement();
				buffer.append(addr.getHostName()).append("/").append(addr.getHostAddress()).append(", ");
			}
			if (buffer.length() > 2)
				buffer.setLength(buffer.length() - 2);
			return buffer.toString();
		}

		private String getMAC() {
			try {
				byte[] mac = ni.getHardwareAddress();
				if (null == mac)
					return none;
				StringBuilder buffer = new StringBuilder(mac.length * 3);
				for (int i = 0; i < mac.length; i++) {
					int value = mac[i] < 0 ? 256 + mac[i] : mac[i];
					String hex = Integer.toHexString(value).toUpperCase();
					if (1 == hex.length())
						buffer.append("0");
					buffer.append(hex).append("-");
				}
				if (buffer.length() > 1)
					buffer.setLength(buffer.length() - 1);
				return buffer.toString();
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String getMTU() {
			try {
				return Integer.toString(ni.getMTU());
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String isLoopback() {
			try {
				return this.wrapBoolean(ni.isLoopback());
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String isPointToPoint() {
			try {
				return this.wrapBoolean(ni.isPointToPoint());
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String isUp() {
			try {
				return this.wrapBoolean(ni.isUp());
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String supportsMulticast() {
			try {
				return this.wrapBoolean(ni.supportsMulticast());
			} catch (SocketException e) {
				e.printStackTrace();
			}
			return none;
		}

		private String wrapBoolean(boolean value) {
			return value ? yes : no;
		}
	}
}
